﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management;
using System.Diagnostics;
using System.Reflection;

namespace hypervmgmtlib.old
{
    using msvm = wmi.root.virtualization.msvm;
    using cim = wmi.root.virtualization.cim;

    

    public class Host_
    {
        public Host_(string hostname)
        {
            this.Hostname = hostname;
        }

        public string Hostname { get; private set; }

        public VM_[] VM
        {
            get
            {
                var instances = msvm.ComputerSystem.GetInstances(Scope, (string)null);
                return instances.Cast<msvm.ComputerSystem>()
                    .Where(x => x.Caption == "Virtual Machine")
                    .Select(x => new VM_(x)).ToArray();
            }
        }

        public VM_ Spawn(string name) { return VM_.Spawn(this, name); }

        public ManagementScope Scope
        {
            get
            {
                return new ManagementScope()
                {
                    Path = new ManagementPath()
                    {
                        Server = Hostname,
                        NamespacePath = @"root\virtualization"
                    }
                };
            }
        }
    }

    [DebuggerDisplay("VM: {Id} {Name}")]
    public class VM_
    {
        public VM_(msvm.ComputerSystem vmObj) { this.vmObj = vmObj; }
        public msvm.ComputerSystem vmObj { get; private set; }

        public static VM_ Spawn(Host_ host, string name) { return null; }

        public string Id { get { return vmObj.Name; } }
        public string Name { get { return vmObj.ElementName; } }

        private SettingData_ SettingData { get { return SettingData_.Of(this); } }

        public Cpu_ Cpu { get { return Cpu_.Of(SettingData); } }
        public Mem_ Mem { get { return Mem_.Of(SettingData); } }
        public Ide_[] Ide { get { return Ide_.Of(SettingData); } }
        public Ide_ Ide0;
        public Ide_ Ide1;
        public Scsi_[] Scsi { get { return Scsi_.Of(SettingData); } }
    }

    public class SettingData_
    {
        public SettingData_(msvm.VirtualSystemSettingData settingDataObj) { this.settingDataObj = settingDataObj; }
        public msvm.VirtualSystemSettingData settingDataObj { get; private set; }

        public static SettingData_ Of(VM_ vm)
        {
            var settingDataObj = util.CreateObj<msvm.VirtualSystemSettingData>(
                       util.GetRelatedObjects(
                           vm.vmObj.Path,
                           "Msvm_VirtualSystemSettingData",
                           "Msvm_SettingsDefineState").Single());
            return new SettingData_(settingDataObj);

        }

        public T[] getRsrc<T>(string clsName)
        {
            return util.GetRelatedObjects(settingDataObj.Path, clsName, null)
                   .Select(x => util.CreateObj<T>(x))
                   .ToArray();
        }

        public msvm.ResourceAllocationSettingData[] getRsrc()
        {
            return getRsrc<msvm.ResourceAllocationSettingData>("Msvm_ResourceAllocationSettingData");
        }
    }


    [DebuggerDisplay("Cpu: {Count}")]
    public class Cpu_
    {
        public Cpu_(msvm.ProcessorSettingData cpuObj) { this.cpuObj = cpuObj; }
        public msvm.ProcessorSettingData cpuObj { get; private set; }

        public static Cpu_ Of(SettingData_ settingData)
        {
            return new Cpu_(settingData.getRsrc<msvm.ProcessorSettingData>("Msvm_ProcessorSettingData").Single());
        }

        public int Count
        {
            get { return (int)cpuObj.VirtualQuantity; }
            set { }
        }
    }

    [DebuggerDisplay("Ram: {Startup}")]
    public class Mem_
    {
        public Mem_(msvm.MemorySettingData memObj) { this.memObj = memObj; }
        private msvm.MemorySettingData memObj;

        public static Mem_ Of(SettingData_ settingData)
        {
            return new Mem_(settingData.getRsrc<msvm.MemorySettingData>("Msvm_MemorySettingData").Single());
        }


        public int Startup
        {
            get { return (int)memObj.VirtualQuantity; }
            set { }
        }
    }

    public interface IController:IEnumerable<IDrive>
    {
        string Address { get; }


        IDrive this[int drvIndex] { get; set; }
        int MaxDrives { get; }
    }

    [DebuggerDisplay("Ide: {Address}")]
    public class Ide_ : IController
    {
        public Ide_(msvm.ResourceAllocationSettingData ideObj) { this.ideObj = ideObj; }
        public msvm.ResourceAllocationSettingData ideObj { get; private set; }

        public static Ide_[] Of(SettingData_ settingData)
        {
            return settingData.getRsrc()
                    .Where(x => x.ResourceSubType == "Microsoft Emulated IDE Controller")
                    .Select(x => new Ide_(x))
                    .ToArray();
        }

        public string Address { get { return ideObj.Address; } }

        public IDrive this[int drvIndex]
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public int MaxDrives
        {
            get { return 2; }
        }

        public IEnumerator<IDrive> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class Scsi_ : IController
    {
        public Scsi_(msvm.ResourceAllocationSettingData scsiObj) { this.scsiObj = scsiObj; }
        private msvm.ResourceAllocationSettingData scsiObj;

        public static Scsi_[] Of(SettingData_ settingData)
        {
            return settingData.getRsrc()
                   .Where(x => x.ResourceSubType == "Microsoft Synthetic SCSI Controller")
                   .Select(x => new Scsi_(x))
                   .ToArray();
        }

        public string Address { get { return scsiObj.Address; } }

        public IDrive this[int drvIndex]
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public int MaxDrives
        {
            get { throw new NotImplementedException(); }
        }

        public IEnumerator<IDrive> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }

    public interface IDrive
    {
        int DrvIndex { get; }
        IMedia Media { get;  }
    }

    
    public class Hdd : IDrive
    {
        public int DrvIndex { get { return 0; } }

        public IMedia Media { get { return null; } }
    }

    public class Dvd : IDrive
    {
        public int DrvIndex { get { return 0; } }
        public IMedia Media { get { return null; } }
    }

    public interface IMedia
    {
        string Connection { get; }
    }

    public class VhdImage : IMedia
    {
        public string Connection { get { return null; } }

        public static VhdImage Set(IDrive drv, string vhdFile)
        {
            return null;
        }
    }

    public class DvdImage : IMedia
    {
        public string Connection { get { return null; } }

        public static DvdImage Set(IDrive drv, string isoFile)
        {
            return null;
        }
    }

    public class HdPassthrough : IMedia
    {
        public string Connection { get { return null; } }
    }

    public class DvdPassthrough : IMedia
    {
        public string Connection { get { return null; } }
    }

}
